<template>
  <div>
    <Breadcrumb :opt-data="breadcrumbOptData"></Breadcrumb>
    <PageLayout>
      <div class="table-container height-100">
        <EZTable
          v-loading="tableLoading"
          :table-id="tableId"
          :table-hdl="tableHdl"
          :rows="deviceData"
          :selectable="true"
          :custom-empty="true"
          @pageChanged="getDeviceData"
          @sizeChanged="getDeviceData"
          @filterChange="getDeviceData"
          @selectionChange="(data) => this.selectDeviceData = data">
          <div slot="customOpts">
            <el-tooltip v-if="selectDeviceData.length > 0" :open-delay="300" placement="left">
              <div slot="content">
                <div v-for="device in selectDeviceData" :key="device._id">{{device.deviceName}}</div>
              </div>
              <div class="display-inline">
                <span>已选择 </span>
                <span class="font-color-primary">{{selectDeviceData.length}}</span>
                <span> 条</span>
              </div>
            </el-tooltip>
          </div>
          <EmptyContent slot="empty" :opt-data="tableOptData"></EmptyContent>
        </EZTable>
      </div>
      <el-dialog
        :visible.sync="showDeviceDialog"
        :close-on-click-modal="false"
        :title="`${!isEditDevice ? '新增' : '编辑'}设备`"
        width="700px"
        center>
        <el-form
          v-loading="deviceFormLoading"
          :ref="deviceFormRef"
          :model="deviceForm"
          :rules="deviceFormRules"
          size="small"
          label-width="130px">
          <el-form-item label="设备型号" prop="model">
            <el-select v-model="deviceForm.model" filterable clearable class="width-100" placeholder="请选择设备型号"
                       @change="modelChanged">
              <el-option :label="model.label" :value="model.value" :key="idx"
                         v-for="(model, idx) in modelData"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="设备协议" prop="protocols">
            <el-button type="primary" size="mini" icon="el-icon-circle-plus-outline"
                       @click="addProtocol">添加协议
            </el-button>
            <el-row v-for="(p, idx) in deviceForm.protocols" :key="idx" class="mar-top-5">
              <el-col :span="12" class="pad-rgt-5">
                <el-select v-model="p.protocol" clearable filterable class="width-100" placeholder="请选择设备协议">
                  <el-option :label="protocol.label" :value="protocol.value" :key="idx"
                             v-for="(protocol, idx) in protocolData"></el-option>
                </el-select>
              </el-col>
              <el-col :span="8">
                <el-input-number v-model="p.deviceChannel" :min="1" placeholder="请填写设备通道"
                                 class="width-100"></el-input-number>
              </el-col>
              <el-col :span="4" class="pad-lft-10">
                <el-button type="danger" icon="el-icon-delete"
                           circle @click="deleteProtocol(idx)"></el-button>
              </el-col>
            </el-row>
            <div class="font-color-danger font-size-12 mar-top-10" style="line-height: 20px">
              <div>若分控已添加此型号的设备，请注意设备的通道与对应的协议是否匹配，</div>
              <div>如：设备id为01011表示通道为1，设备id为01012表示通道为2。</div>
            </div>
          </el-form-item>
          <el-form-item label="是否是单向设备">
            <el-radio-group v-model="deviceForm.unidirectional">
              <el-radio :label="1">是</el-radio>
              <el-radio :label="0">否</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="设备版本" prop="deviceVer">
            <el-input v-model="deviceForm.deviceVer" class="width-50" placeholder="请填写设备版本"></el-input>
          </el-form-item>
          <el-form-item label="最小控制间隔(ms)">
            <el-input-number class="width-50" v-model="deviceForm.minCtrInterval" :min="0"
                             :step="100"></el-input-number>
          </el-form-item>
          <el-form-item label="备注">
            <el-input type="textarea" v-model="deviceForm.remarks" placeholder="请填写备注"></el-input>
          </el-form-item>
        </el-form>
        <div class="text-align-right">
          <el-button size="medium" @click="clickCancelBtn">取消</el-button>
          <el-button size="medium" type="primary" @click="clickSubmitBtn">保存</el-button>
        </div>
      </el-dialog>
    </PageLayout>
  </div>
</template>

<script>
  import {tableIdConfig, tableOptBtnConfig} from '@/config/table';
  import {componentTypeArray, momentFormat} from "@/config/common";
  import {msgCode} from "@/config/string";
  import {secretHdl} from "@/modules/secretHdl";
  import {confirmHandle, deepCopyWithJson, messageHandle, downloadExportData, getUserInfo} from "@/utils";
  import {assembleTableOptBtn, getTableConfig, TableStateHdl} from "@/modules/routeParamStateHdl";
  import deviceTableCfg from "../../config/table/device";
  import EZTable from '../../components/table/EZTable';

  const FileSaver = require('file-saver');

  export default {
    name: "DeviceList",
    components: {
      EZTable
    },
    data() {
      return {
        userInfo: getUserInfo(),
        tableLoading: true,
        tableId: tableIdConfig.device,
        tableHdl: null,
        deviceData: [],
        deviceSelIds: [],
        showDeviceDialog: false,
        deviceFormLoading: false,
        modelData: [],
        protocolData: [],
        selectDeviceData: [],
        deviceAllData: [],
        deviceForm: {},
        deviceFormRules: {
          model: [
            {required: true, message: '请选择设备型号', trigger: 'blur'}
          ],
          deviceVer: [
            {required: true, message: '请填写设备版本', trigger: 'blur'}
          ],
        },
        deviceFormRef: 'deviceFormRef',
        isEditDevice: false
      }
    },
    computed: {
      breadcrumbOptData() {
        if (this.userInfo.role === 'guest') {
          return [
            {
              type: 'btn',
              label: '导出至集控',
              icon: 'icon-zujiantubiao-daochu',
              callback: () => {
                this.exportToManager();
              }
            },
            {
              type: 'btn',
              label: '导出至分控',
              icon: 'icon-zujiantubiao-daochu',
              callback: () => {
                this.exportToControl();
              }
            },
            {
              type: 'btn',
              label: '导出 Excel',
              icon: 'icon-zujiantubiao-daochu',
              callback: () => {
                this.exportToExcel();
              }
            }
          ];
        }else{
          return [
            {
              type: 'btn',
              label: '导出至集控',
              icon: 'icon-zujiantubiao-daochu',
              callback: () => {
                this.exportToManager();
              }
            },
            {
              type: 'btn',
              label: '导出至分控',
              icon: 'icon-zujiantubiao-daochu',
              callback: () => {
                this.exportToControl();
              }
            },
            {
              type: 'btn',
              label: '导出 Excel',
              icon: 'icon-zujiantubiao-daochu',
              callback: () => {
                this.exportToExcel();
              }
            },
            {
              type: 'btn',
              label: '新增设备',
              icon: 'icon-tianjia',
              callback: () => {
                this.clickCreateBtn();
              }
            },
          ];
        }

      },
      tableOptData() {
        return [
          {
            type: 'btn',
            label: '新增设备',
            icon: 'icon-tianjia',
            callback: () => {
              this.clickCreateBtn();
            }
          }
        ];
      },
    },
    activated() {
      this.initTableConfig();
      this.initDeviceForm();
      this.getModelData();
      this.getDeviceData();
      this.getDeviceAll()
    },
    methods: {
      initTableConfig() {
        if (this.tableHdl) return;
        const {columns = [], filters = []} = getTableConfig(this.tableId, deviceTableCfg);
        assembleTableOptBtn(columns, ({type = '', data = {}}) => {
          if (!type) return;
          const device = deepCopyWithJson(data);
          switch (type) {
            case tableOptBtnConfig.edit.type:
              this.showDeviceDialog = true;
              this.isEditDevice = true;
              this.deviceForm = device;
              this.getProtocolData(device.deviceType);
              break;
            case tableOptBtnConfig.delete.type:
              this.deleteDevice(device);
              break;
            default:
              break;
          }
        });
        this.tableHdl = new TableStateHdl(this.$route.name, this.tableId, columns, filters);
      },
      modelChanged(val) {
        let deviceTypeNo = this.modelData.find(item => item._id === val).deviceTypeNo
        let deviceType = this.deviceAllData.find(item => item.deviceTypeNo === deviceTypeNo)._id
        this.getProtocolData(deviceType)
      },
      initDeviceForm() {
        this.deviceForm = {
          model: '',
          protocols: [],
          unidirectional: 0,
          deviceVer: `v1.0.0#${moment().format(momentFormat.datestamp)}1`,
          description: '',
          minCtrInterval: 1000,
          remarks: '',
        }
      },
      resetDeviceForm() {
        this.initDeviceForm();
        const deviceForm = this.$refs[this.deviceFormRef];
        deviceForm && deviceForm.resetFields();
      },
      clickCreateBtn() {
        this.isEditDevice && this.resetDeviceForm();
        this.showDeviceDialog = true;
        this.isEditDevice = false;
      },
      tableSelectionChanged(rows = []) {
        this.deviceSelIds = _.pluck(rows, '_id');
      },
      getModelData() {
        API.model.modelAll().then(result => {
          const {data = []} = result;
          this.modelData = data;
        }).catch(err => {
          console.log('err', err)
        });
      },
      getProtocolData(deviceType) {
        API.protocol.protocolAll({deviceType: deviceType}).then(result => {
          const {data = []} = result;
          this.protocolData = data;
        }).catch(err => {
          console.log('err', err)
        });
      },
      getDeviceData() {
        this.tableLoading = true;
        const selector = {};
        const tableParam = this.tableHdl.assembleTableParam();
        API.device.deviceList({selector, ...tableParam}).then(result => {
          this.tableLoading = false;
          const {data = [], total = 0} = result;
          const assembleCommandText = (src = []) =>
            src.map((s, index) => `${s.deviceChannel}:${s.protocolName}`).join('<br>');
          this.deviceData = data.map(d => {
            return {
              ...d,
              adminEditBtn: this.userInfo.role!=='guest',
              protocolText: assembleCommandText(d.protocols),
            }
          });
          this.tableHdl.total = total;
        }).catch(err => {
          console.log('err', err)
          this.tableLoading = false;
        });
      },
      getDeviceAll() {
        API.deviceType.deviceTypeAll().then(result => {
          const {data = []} = result;
          this.deviceAllData = data;
        }).catch(err => {
          console.log('err', err)
        });
      },
      deleteDevice(device = {}) {
        confirmHandle({label: `确定要删除设备：${device.deviceName} 吗?`}).then(() => {
          API.device.deviceDelete({_id: device._id}).then(result => {
            messageHandle({code: msgCode.DELETE_SUCCESS, title: '设备'});
            this.tableHdl.judgeTableMatched();
            this.getDeviceData();
            this.resetDeviceForm();
          });
        }).catch(() => {
        });
      },
      addProtocol() {
        const lastProtocol = _.last(this.deviceForm.protocols) || {};
        const lastChannel = lastProtocol.deviceChannel || 0;
        this.deviceForm.protocols.push({
          deviceChannel: lastChannel + 1,
          protocol: ''
        });
      },
      deleteProtocol(idx) {
        this.deviceForm.protocols.splice(idx, 1);
      },
      clickCancelBtn() {
        this.showDeviceDialog = false
      },
      clickSubmitBtn() {
        this.$refs[this.deviceFormRef].validate((valid) => {
          if (!valid) return;
          const {protocols = []} = this.deviceForm;
          // 校验设备协议及协议通道是否重复
          const checkProtocol = () => {
            let duplicate = false;
            let invalid = false;
            const pIdSet = new Set();
            const pChannelSet = new Set();
            for (let i = 0; i < protocols.length; i++) {
              const ptc = protocols[i];
              const {protocol = '', deviceChannel = 1} = ptc;
              if (!protocol) {
                invalid = true;
                break;
              }
              if (pIdSet.has(protocol) || pChannelSet.has(deviceChannel)) {
                duplicate = true;
                break;
              }
              pIdSet.add(protocol);
              pChannelSet.add(deviceChannel);
            }
            return {invalid, duplicate}
          };
          const {invalid, duplicate} = checkProtocol();
          if (invalid) {
            messageHandle({type: 'warning', msg: '设备协议不能为空！'});
            return;
          }
          if (duplicate) {
            messageHandle({type: 'warning', msg: '设备协议及协议通道不能重复！'});
            return;
          }
          this.deviceFormLoading = true;
          if (!this.isEditDevice) {
            API.device.deviceAdd(this.deviceForm).then(result => {
              messageHandle({code: msgCode.ADD_SUCCESS, title: '设备'});
              this.showDeviceDialog = false;
              this.deviceFormLoading = false;
              this.getDeviceData();
              this.resetDeviceForm();
            }).catch(err => {
              console.log('err', err)
              this.deviceFormLoading = false;
            });
          } else {
            API.device.deviceEdit(this.deviceForm).then(result => {
              messageHandle({code: msgCode.EDIT_SUCCESS, title: '设备'});
              this.showDeviceDialog = false;
              this.deviceFormLoading = false;
              this.getDeviceData();
              this.resetDeviceForm();
            }).catch(err => {
              console.log('err', err)
              this.deviceFormLoading = false;
            });
          }
        });
      },
      exportToControl() {
        const param = this.selectDeviceData.length ? {_id: {$in: _.map(this.selectDeviceData, '_id')}} : {};
        const labelText = this.selectDeviceData.length > 0 ? `导出${this.selectDeviceData.length}条数据` : '导出全部数据';
        confirmHandle({label: `是否确定要${labelText} ？`}).then(() => {
          this.tableLoading = true;
          API.device.deviceExportControl({selector: param}).then(result => {
            const {devices = [], metadata = []} = result.data.data || {};
            const ts = moment().format(momentFormat.dateTimeDetailFlat);
            const rand = Math.random() * 16;

            const exportHandle = (payload) => {
              const data = `<<<\nezControl\nV1.0.0\n${ts}\n${rand}\n${payload.length}\n${payload}\n>>>`;
              const deviceDataBlob = new Blob([data]);
              if (this.selectDeviceData.length > 1) {
                FileSaver.saveAs(deviceDataBlob, `多设备集合-${this.selectDeviceData.length}.cfg`);
              } else if (this.selectDeviceData.length === 1) {
                const deviceInfo = devices[0].device_extra_info || {};
                const deviceVer = devices[0].device_ver || '';
                FileSaver.saveAs(deviceDataBlob, `${deviceInfo.type_name}-${deviceInfo.manufacturer_name}-${deviceInfo.series_name}-${deviceInfo.model_name}-${deviceVer}.cfg`);
              } else {
                FileSaver.saveAs(deviceDataBlob, "设备全量导出.cfg");
              }
            }

            confirmHandle({
              label: `是否导出设备元数据(旧版本分控请选择不导出) ？`,
              confirmText: '是',
              cancelText: '否',
              preventDefaultClose: true
            }).then(() => {
              const payload = secretHdl.encrypt(JSON.stringify({devices, metadata}), `${ts}${rand}`);
              exportHandle(payload);
            }).catch((err) => {
              const payload = secretHdl.encrypt(JSON.stringify(devices), `${ts}${rand}`);
              exportHandle(payload);
            });
            this.tableLoading = false;
          }).catch(err => {
            this.tableLoading = false;
            console.log('err', err)
          });
        }).catch((err) => {
          console.log('##### err #####', err);
        });
      },
      exportToManager() {
        const param = this.selectDeviceData.length ? {_id: {$in: _.map(this.selectDeviceData, '_id')}} : {};
        const lableText = this.selectDeviceData.length > 0 ? `导出${this.selectDeviceData.length}条数据` : '导出全部数据'
        confirmHandle({label: `是否确定要${lableText} ？`}).then(() => {
          this.tableLoading = true
          API.device.deviceExportManager(param).then(result => {
            const {
              deviceType = {}, manufacture = {},
              series = {}, model = {}, generalCommand = {}
            } = result.data || {};
            const deviceTypeBlob = new Blob([JSON.stringify({...deviceType, type: 'deviceType'})]);
            FileSaver.saveAs(deviceTypeBlob, "device_type.json");
            const manufactureBlob = new Blob([JSON.stringify({...manufacture, type: 'manufacture'})]);
            FileSaver.saveAs(manufactureBlob, "manufacture.json");
            const seriesBlob = new Blob([JSON.stringify({...series, type: 'series'})]);
            FileSaver.saveAs(seriesBlob, "series.json");
            const modelBlob = new Blob([JSON.stringify({...model, type: 'model'})]);
            FileSaver.saveAs(modelBlob, "model.json");
            const generalCommandBlob = new Blob([JSON.stringify({...generalCommand, type: 'generalCommand'})]);
            FileSaver.saveAs(generalCommandBlob, "generalCommand.json");
            this.tableLoading = false
          }).catch(err => {
            this.tableLoading = false
            console.log('err', err)
          });
        }).catch(() => {
        });
      },
      exportToExcel() {
        const param = this.selectDeviceData.length ? {_id: {$in: _.map(this.selectDeviceData, '_id')}} : {};
        const lableText = this.selectDeviceData.length > 0 ? `导出${this.selectDeviceData.length}条数据` : '导出全部数据'
        confirmHandle({label: `是否确定要${lableText} ？`}).then(() => {
          this.tableLoading = true
          API.device.deviceExportExcel(param).then(result => {
            this.tableLoading = false
            // FileSaver.saveAs(deviceTypeBlob, "设备能力集和.xlsx");
            downloadExportData(result.data, '设备能力集合.xlsx');
          }).catch(err => {
            this.tableLoading = false
            console.log('err', err)
          });
        }).catch(() => {
        });
      }
    },
  }
</script>

<style scoped>

</style>
